#include "sym_detect_plugin.h"
Q_EXPORT_PLUGIN(sym_detect_plugin)

#include "sym_detect_widget.h"
#include "StarlabDrawArea.h"

// debug demos
#include "meanshiftDemo.h"
meanshiftDemo *ms_demo = new meanshiftDemo;

#include "ICP.h"

sym_detect_plugin::sym_detect_plugin()
{
	widget = NULL;
}

void sym_detect_plugin::create()
{
	if (!widget)
	{
		widget = new sym_detect_widget(this);

		ModePluginDockWidget *dockwidget = new ModePluginDockWidget(mainWindow());
		dockwidget->setWidget(widget);
		dockwidget->setWindowTitle("Symmetry detector");

		mainWindow()->addDockWidget(Qt::RightDockWidgetArea, dockwidget);
	}
}

void sym_detect_plugin::destroy()
{

}


void sym_detect_plugin::test()
{
	activeSymmetryDetector()->test();
	//ms_demo->demo();
	//testICP();

	drawArea()->resetViewport();
}


void sym_detect_plugin::debug()
{
	//activeSymmetryDetector()->visualizePeers();
	//ms_demo->stepForward1();
	
	drawArea()->updateGL();
}


void sym_detect_plugin::decorate()
{
	// draw point as circle
	glEnable(GL_POINT_SMOOTH);

	activeSymmetryDetector()->draw();
	//ms_demo->draw();
}

SymmetryDetector* sym_detect_plugin::activeSymmetryDetector()
{
	QString mesh_name = mesh()->name;

	// Create a symmetry detector
	if (!sym_detectors.contains(mesh_name))
	{
		normalizeMesh();

		SymmetryDetector *detector = new SymmetryDetector(mesh());
		detector->numFeaturePoints = widget->numFeaturePoints();
		detector->numBasePoints = widget->numBasePoints();
		detector->pairingThreshold = widget->pairingThreshold();
		detector->distinctiveRatio = widget->distinctiveRatio();

		sym_detectors[mesh_name] = detector;

		// connects
		this->connect(detector, SIGNAL(addModelToDocument(SurfaceMeshModel*)), SLOT(addModelToDocument(SurfaceMeshModel*)));
		this->connect(detector, SIGNAL(showStatusMessage(char*)), SLOT(showStatusMessage(char*)));
	}

	return sym_detectors[mesh_name];
}

void sym_detect_plugin::testICP()
{
	QStringList layers;
	foreach(StarlabModel* model, document()->models())
		if(SurfaceMesh::isA(model) && model!=mesh())
			layers << model->name;
	QString layer = layers.back();

	Model *m1 = SurfaceMesh::safe_cast(document()->selectedModel());
	Model *m2 = SurfaceMesh::safe_cast(document()->getModel(layer));
	m1->color = QColor(186, 172, 96);
	m2->color = QColor(86, 117, 147);

	ICP(m1, m2);
}

void sym_detect_plugin::normalizeMesh()
{
	mesh()->updateBoundingBox();
	Vec3d center(mesh()->bbox().center());

	QVector3D s = mesh()->bbox().size();
	double scale = qMax(s.x(), qMax(s.y(), s.z()));

	Vector3VertexProperty points = mesh()->vertex_coordinates();
	foreach( Vertex v, mesh()->vertices()) 
	{
		points[v] -= center;
		points[v] /= scale;
	}
	
	mesh()->updateBoundingBox();
	drawArea()->resetViewport();
}

void sym_detect_plugin::detectReflection()
{
	activeSymmetryDetector()->detectReflections();

	activeSymmetryDetector()->visualizeReflections();
}

void sym_detect_plugin::setNumFeaturePoints( int n )
{
	activeSymmetryDetector()->numFeaturePoints = n;
}

void sym_detect_plugin::setNumBasePoints( int n )
{
	activeSymmetryDetector()->numBasePoints = n;
}

void sym_detect_plugin::setPairingThreshold( double thr )
{
	activeSymmetryDetector()->pairingThreshold = thr;
}

void sym_detect_plugin::setDistinctiveRatio( double ratio )
{
	activeSymmetryDetector()->distinctiveRatio = ratio;
}

void sym_detect_plugin::showPoints( int show )
{
	activeSymmetryDetector()->showPoints = show;
	drawArea()->updateGL();
}

void sym_detect_plugin::showSignatures( int show )
{
	activeSymmetryDetector()->showPointSignatures = show;
	drawArea()->updateGL();
}

void sym_detect_plugin::showPrunedSignatures( int show )
{
	activeSymmetryDetector()->showPrunedSignatures = show;
	drawArea()->updateGL();
}

void sym_detect_plugin::addModelToDocument( SurfaceMeshModel *model )
{
	document()->addModel(model);
}

void sym_detect_plugin::showStatusMessage( char *msg )
{
	showMessage(msg);
}

